library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity multirisc is
	Port ( 	clk : in  STD_LOGIC;
			
			debug_pins : out std_logic_vector (7 downto 0);
			
			ledg : out std_logic_vector(7 downto 0);
			ledr : out std_logic_vector(9 downto 0);
			
			sram_addr     : out std_logic_vector(17 DOWNTO 0);
		    sram_data     : inout std_logic_vector(15 DOWNTO 0);
			sram_wren     : out std_logic;
			sram_ub		  : out std_logic;
			sram_lb		  : out std_logic;
			sram_ce		  : out std_logic;
			sram_oe		  : out std_logic;
			
			hex0 : out std_logic_vector(6 downto 0);
			hex1 : out std_logic_vector(6 downto 0);
			hex2 : out std_logic_vector(6 downto 0);
			hex3 : out std_logic_vector(6 downto 0);
			
			TDI : in std_logic;   		--// CPLD -> FPGA (data in)
			TCK : in std_logic;  		--// CPLD -> FPGA (clk)
			TCS : in std_logic;  		--// CPLD -> FPGA (CS)
			TDO : out std_logic  		--// FPGA -> CPLD (data out)		
			
			
			--test_outputs : out std_logic_vector(31 downto 0)
			
		);		 
end multirisc;


architecture Behavioral of multirisc is

	-- debug
	signal debug_counter : unsigned(31 downto 0) := (others =>'0');
	
	signal tdi_buffer : std_logic;
	signal tck_buffer : std_logic;
	signal tcs_buffer : std_logic;
	signal tdo_out : std_logic;
	
	signal usb_write : std_logic := '0';
	
	signal timeout_debug : std_logic;
	
	signal valid_usb_data : unsigned(7 downto 0);
	signal valid_usb_data_en : std_logic;
	
	-- clocks
	signal clk_150 : std_logic;
	
	-- wires
	signal usb_rec_valid : std_logic;
	signal usb_rec_value: unsigned(7 downto 0);
	
	signal usb_fifo_words : std_logic_vector(8 downto 0);
	
	signal module_data_valid : std_logic;
	signal module_data : unsigned(7 downto 0);
	signal to_module : unsigned(7 downto 0);
	
	signal usb_out_valid : std_logic;
	signal usb_out : unsigned(7 downto 0); 
	signal usb_out_empty : std_logic;
	
	
	CONSTANT      num_requester_read      : natural := 3;
	constant      num_requester_write     : natural := 2;
	constant      num_frame_sender		  : natural := 1;
	
	
	signal request_write      : unsigned (num_requester_write-1 DOWNTO 0);
	signal request_read       : unsigned (num_requester_read-1 DOWNTO 0);
	signal in_sram_wr_addr    : std_logic_vector((18*num_requester_write)-1 DOWNTO 0);
	signal in_sram_wr_data    : std_logic_vector((16*num_requester_write)-1 DOWNTO 0);
	signal in_sram_rq_addr    : std_logic_vector((18*num_requester_read)-1 DOWNTO 0); 
	signal sram_scheduling_done_write : std_logic;
	signal sram_scheduling_nr_write : std_logic_vector (num_requester_write-1 DOWNTO 0);
	signal sram_scheduling_done_read : std_logic;
	signal sram_scheduling_nr_read : std_logic_vector (num_requester_read-1 DOWNTO 0);
	signal out_sram_read_addr     : std_logic_vector(17 DOWNTO 0);
	signal out_sram_read_data     : std_logic_vector(15 DOWNTO 0);
	signal out_sram_read_valid    : std_logic;

	
	signal request_frame            :  unsigned (num_frame_sender-1 DOWNTO 0);
    signal in_to_send_frame         :   std_logic_vector((8*num_frame_sender)-1 DOWNTO 0);
    signal fifo_halffull_frame      :   std_logic := '0';
    signal write_enable_frame       :    std_logic_vector(num_frame_sender-1 DOWNTO 0);
    signal schedule_nr_out_frame    :  std_logic_vector (num_frame_sender-1 DOWNTO 0);
    signal scheduling_done_out_frame :  std_logic;
    signal read_enable_frame        :   std_logic;
    signal out_to_send_frame        :   std_logic_vector(7 DOWNTO 0);
    signal data_to_fifo_we_frame    :   std_logic;

	
	
	component system_clock
	PORT
	(
		inclk0	: IN STD_LOGIC  := '0';
		c0		: OUT STD_LOGIC 
	);
	end component;
	
	component usb_transceiver is Port 
	( 	clk : in  STD_LOGIC;
		TDI : in std_logic;   		--// CPLD -> FPGA (data in)
		TCK : in std_logic;  		--// CPLD -> FPGA (clk)
		TCS : in std_logic;  		--// CPLD -> FPGA (CS)
		TDO : out std_logic; 		--// FPGA -> CPLD (data out)
		in_valid : out std_logic;
		in_value : out unsigned(7 downto 0);
		out_we : in std_logic;
		out_full : out std_logic;
		out_empty : out std_logic;
		out_data : in unsigned(7 downto 0);
		out_words : out std_logic_vector(8 downto 0)
		);	
	end component;	 
	
	
	component framedecoder is Port 
	( 	clk : in  STD_LOGIC;
		usb_data_valid : in std_logic;
		usb_data : in unsigned(7 downto 0);
		module_data_valid : out std_logic;
		module_data : out unsigned(7 downto 0);
		to_module : out unsigned(7 downto 0)
	);		 
	end component;
	
	
	component testframe is Port 
	( 	clk : in  STD_LOGIC;
		fifo_empty : in std_logic;
		data_valid : out std_logic;
		data : out unsigned(7 downto 0)
	);		 
	end component;
	
	
	component sram_access IS
    GENERIC(
       num_requester_read      : natural := 4;
       num_requester_write      : natural := 4
    );
    PORT( 
       clk                : IN   std_logic;
       request_write      : IN   unsigned (num_requester_write-1 DOWNTO 0);
       request_read       : IN   unsigned (num_requester_read-1 DOWNTO 0);
       in_sram_wr_addr    : in std_logic_vector((18*num_requester_write)-1 DOWNTO 0);
       in_sram_wr_data    : in std_logic_vector((16*num_requester_write)-1 DOWNTO 0);
       in_sram_rq_addr    : in std_logic_vector((18*num_requester_read)-1 DOWNTO 0); 
       sram_scheduling_done_write : out std_logic;
       sram_scheduling_nr_write : out std_logic_vector (num_requester_write-1 DOWNTO 0);
       sram_scheduling_done_read : out std_logic;
       sram_scheduling_nr_read : out std_logic_vector (num_requester_read-1 DOWNTO 0);
       out_sram_read_addr     : out   std_logic_vector(17 DOWNTO 0);
       out_sram_read_data     : out   std_logic_vector(15 DOWNTO 0);
       out_sram_read_valid    : out   std_logic;
       sram_addr     : out   std_logic_vector(17 DOWNTO 0);
       sram_data     : inout std_logic_vector(15 DOWNTO 0);
       sram_wren          : out   std_logic 
    );
    end component;


	component led_updater IS
    GENERIC(
       mem_addr      : std_logic_vector(17 downto 0) := "000000000001111111";
       slowness      : natural := 20
    );
    PORT( 
       clk                : IN std_logic;  
       grant              : IN std_logic;  
       grant_valid        : IN std_logic;
       sram_read_addr     : in std_logic_vector(17 DOWNTO 0);
       sram_read_data     : in std_logic_vector(15 DOWNTO 0);
       sram_read_valid    : IN std_logic;
       request_out      : out std_logic;
       request_addr     : out std_logic_vector(17 DOWNTO 0);
       led_value        : out std_logic_vector(9 downto 0)  
    );
    end component;
  
  
    component extern_sram_writer IS
    PORT( 
       clk                : IN std_logic;  
       datain             : IN unsigned(7 downto 0);  
       datain_valid       : IN std_logic;  
       module_enable	  : IN std_logic;
       grant              : IN std_logic;  
       grant_valid        : IN std_logic;
       request_out      : out std_logic;
       request_data     : out std_logic_vector(15 DOWNTO 0);
       request_addr     : out std_logic_vector(17 DOWNTO 0)
    );
    end component;
    
    
    component framesend_unit IS
    GENERIC(
       num_requester      : natural := 4
    );
    PORT( 
       clk                : IN   std_logic;
       request            : IN   unsigned (num_requester-1 DOWNTO 0);
       in_to_send         : in   std_logic_vector((8*num_requester)-1 DOWNTO 0);
       fifo_halffull      : in   std_logic;
       write_enable       : in    std_logic_vector(num_requester-1 DOWNTO 0);
       schedule_nr_out    : out std_logic_vector (num_requester-1 DOWNTO 0);
       scheduling_done_out : out std_logic;
       read_enable        : out   std_logic;
       out_to_send        : out   std_logic_vector(7 DOWNTO 0);
       data_to_fifo_we    : out   std_logic
    );
    end component;
  
    
    component sram_streamer IS
    PORT( 
       clk                : IN std_logic;  
       datain             : IN unsigned(7 downto 0);  
       datain_valid       : IN std_logic; 
       module_enable	     : IN std_logic;
       grant              : IN std_logic;  
       grant_valid        : IN std_logic;
       sram_read_addr     : in std_logic_vector(17 DOWNTO 0);
       sram_read_data     : in std_logic_vector(15 DOWNTO 0);
       sram_read_valid    : IN std_logic;
       request_sram      : out std_logic;
       request_addr      : out std_logic_vector(17 DOWNTO 0);  
       frame_rden        : in std_logic;
       grant_frame       : in std_logic;
       grant_frame_valid : in std_logic;
       request_frame     : out std_logic;
       data_to_frame     : out std_logic_vector(7 DOWNTO 0);
       frame_wren        : out std_logic      
    );
    end component;

	
	component hex_lookup is port
	(	to_hexdisplay  : in unsigned(15 downto 0);	
		hex0  : out std_logic_vector(6 downto 0);
		hex1  : out std_logic_vector(6 downto 0);
		hex2  : out std_logic_vector(6 downto 0);
		hex3  : out std_logic_vector(6 downto 0)
	);
	end component;	
	
	
	component cores_enviroment IS
    GENERIC (
            cores      : natural := 1
        );
    Port(
        clk		             : IN STD_LOGIC;
        
        datain            : IN unsigned(7 downto 0);  
        datain_valid      : IN std_logic;
        module_enable	    : IN std_logic;          
        --sram read interface
        sram_read_addr    : in std_logic_vector(17 DOWNTO 0);
        sram_read_data    : in std_logic_vector(15 DOWNTO 0);
        sram_read_valid   : IN std_logic;
        grant_read        : IN std_logic;  
        grant_valid_read  : IN std_logic;
        request_out_read  : out std_logic;
        request_addr_read : out std_logic_vector(17 DOWNTO 0); 
        --sram write interface
        grant_write            : IN std_logic;  
        grant_valid_write      : IN std_logic;
        request_out_write      : out std_logic;
        request_data_write     : out std_logic_vector(15 DOWNTO 0);
        request_addr_write     : out std_logic_vector(17 DOWNTO 0) 
    );
    END component;

	
		 
	
	
--############################################################################	
begin
--############################################################################


	system_clock_inst : system_clock PORT MAP (
		inclk0	=> clk,
		c0	 	=> clk_150
	);


	usb_transceiver1 : usb_transceiver port map
	(	clk => clk_150,
		tdi => tdi,
		tck => tck,
		tcs => tcs,
		tdo => tdo_out,	
		in_valid => usb_rec_valid,
		in_value => usb_rec_value,
		out_we => data_to_fifo_we_frame,
		out_full => open,
		out_empty => usb_out_empty,
		out_data => unsigned(out_to_send_frame),
		out_words => usb_fifo_words
	);
	
	
	framedecoder1 : framedecoder Port map 
	( 	clk => clk_150,
		usb_data_valid => usb_rec_valid,
		usb_data => usb_rec_value,
		module_data_valid => module_data_valid,
		module_data => module_data,
		to_module => to_module
	);	
	
	
	--testframe1: testframe Port map
	--( 	clk => clk_150,
	--	fifo_empty => usb_out_empty,
	--	data_valid => usb_out_valid,
	--	data => usb_out
	--);	 
	
	
	hex_lookup1 : hex_lookup port map
	(	to_hexdisplay  => debug_counter(7 downto 0) & unsigned(usb_fifo_words(7 downto 0)),
		hex0  => hex0,
		hex1  => hex1,
		hex2  => hex2,
		hex3  => hex3
	);
	
	
	sram_access1 : sram_access
	GENERIC map(
       num_requester_read     => num_requester_read,
       num_requester_write    => num_requester_write
    )
    PORT map( 
       clk               => clk_150,
       request_write     => request_write,
       request_read       => request_read,
       in_sram_wr_addr    => in_sram_wr_addr,
       in_sram_wr_data    => in_sram_wr_data,
       in_sram_rq_addr   => in_sram_rq_addr,
       sram_scheduling_done_write => sram_scheduling_done_write,
       sram_scheduling_nr_write => sram_scheduling_nr_write,
       sram_scheduling_done_read => sram_scheduling_done_read,
       sram_scheduling_nr_read => sram_scheduling_nr_read,
       out_sram_read_addr  => out_sram_read_addr,
       out_sram_read_data  => out_sram_read_data,
       out_sram_read_valid => out_sram_read_valid,
       sram_addr  => sram_addr,
       sram_data => sram_data,
       sram_wren   => sram_wren
    );
    
    
    extern_sram_writer1 : extern_sram_writer
    PORT map( 
       clk                => clk_150,  
       datain             => module_data, 
       datain_valid       => module_data_valid,
       module_enable 	  => to_module(0),  
       grant              => sram_scheduling_nr_write(0), 
       grant_valid        => sram_scheduling_done_write,
       request_out      => request_write(0),
       request_data     => in_sram_wr_data(15 downto 0),
       request_addr     => in_sram_wr_addr(17 downto 0)
    );


	led_updater1 : led_updater
    GENERIC map(
       mem_addr      =>  "000000000001111111",
       slowness      => 10
    )
    PORT map( 
       clk            => clk_150, 
       grant          => sram_scheduling_nr_read(0),  
       grant_valid       => sram_scheduling_done_read,
       sram_read_addr     => out_sram_read_addr,
       sram_read_data     => out_sram_read_data,
       sram_read_valid    => out_sram_read_valid,
       request_out      => request_read(0),
       request_addr     => in_sram_rq_addr(17 downto 0),
       led_value        => ledr  
    );


	framesend_unit1 : framesend_unit
    GENERIC map(
       num_requester      => num_frame_sender
    )
    PORT map( 
       clk                => clk_150,
       request            => request_frame,
       in_to_send         => in_to_send_frame,
       fifo_halffull      => usb_fifo_words(8),
       write_enable       => write_enable_frame,
       schedule_nr_out    => schedule_nr_out_frame,
       scheduling_done_out => scheduling_done_out_frame,
       read_enable        => read_enable_frame,
       out_to_send        => out_to_send_frame,
       data_to_fifo_we    => data_to_fifo_we_frame
    );
        
        
    sram_streamer1 : sram_streamer 
    PORT map( 
       clk                => clk_150,  
       datain             => module_data,
       datain_valid       => module_data_valid,
       module_enable 	  => to_module(1),  
       grant              => sram_scheduling_nr_read(1),
       grant_valid        => sram_scheduling_done_read,
       sram_read_addr     => out_sram_read_addr,
       sram_read_data     => out_sram_read_data,
       sram_read_valid    => out_sram_read_valid,
       request_sram      => request_read(1),
       request_addr      => in_sram_rq_addr(35 downto 18),
       frame_rden        => read_enable_frame,
       grant_frame       => schedule_nr_out_frame(0),
       grant_frame_valid => scheduling_done_out_frame,
       request_frame     => request_frame(0),
       data_to_frame     => in_to_send_frame,
       frame_wren        => write_enable_frame(0)    
    );
    

	cores_enviroment1 : cores_enviroment
    GENERIC map(
            cores      => 1
        )
    Port map(
        clk		             => clk_150,
        
        datain            => module_data, 
        datain_valid      => module_data_valid,
        module_enable	     => to_module(2),  
                   
        sram_read_addr     => out_sram_read_addr,
        sram_read_data     => out_sram_read_data,
        sram_read_valid    => out_sram_read_valid,
        grant_read              => sram_scheduling_nr_read(2),
        grant_valid_read        => sram_scheduling_done_read,
        request_out_read        => request_read(2),
        request_addr_read       => in_sram_rq_addr(53 downto 36),
      
        grant_write            => sram_scheduling_nr_write(1),
        grant_valid_write      => sram_scheduling_done_write,
        request_out_write      => request_write(1),
        request_data_write     => in_sram_wr_data(31 downto 16),
        request_addr_write     => in_sram_wr_addr(35 downto 18)
    );

	


	-- debug	
	process (clk_150)
	begin
		if rising_edge(clk_150) then
			tdi_buffer <= tdi;
			tck_buffer <= tck;
			tcs_buffer <= tcs;
	
			--if module_data_valid='1' then
			if data_to_fifo_we_frame='1' then
				debug_counter <= debug_counter + 1;
				valid_usb_data <= module_data;
				valid_usb_data_en <= '1';
			else
				valid_usb_data_en <= '0';
			end if;
				
		end if;
	end process;

	tdo <= tdo_out;
	
	ledg <= std_logic_vector(valid_usb_data);
	
	
	sram_ub	<= '0';
	sram_lb	<= '0';
	sram_ce	<= '0';
	sram_oe	<= '0';
			
			
		
	debug_pins(0) <= tdi_buffer;
	debug_pins(1) <= tck_buffer;
	debug_pins(2) <= tcs_buffer;
	debug_pins(3) <= tdo_out;
	
	debug_pins(7 downto 4) <= (others => '0');
	

end Behavioral;









